﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Threading.Tasks;
using System.Windows;
using StyleMVVM.DependencyInjection;
using StyleMVVM.Utilities;
#if NETFX_CORE
using Windows.ApplicationModel.Resources;
#else
using StyleMVVM.Strings;

#endif
#if !DOT_NET
using Windows.Foundation;
using Windows.UI.Popups;

#else

#endif

namespace StyleMVVM.View.Impl
{
	public sealed class MessageBoxService : IMessageBoxService
	{
		public static void RegisterExport(IDependencyInjectionContainer container)
		{
			container.Register(typeof(MessageBoxService)).As(typeof(IMessageBoxService)).
			          AndSharedPermenantly();
		}

#if NETFX_CORE

		public async void Notify(string message)
		{
			await InternalShow(message);
		}

		public async void Notify(string message, string title)
		{
			await InternalShow(message, title);
		}

		public async void Notify(string message, string title, string buttonText)
		{
			await InternalShow(message, title, buttonText);
		}

		public IAsyncOperation<string> Show(string message)
		{
			return InternalShow(message, null, null).AsAsyncOperation();
		}

		public IAsyncOperation<string> Show(string message, string title, params string[] commands)
		{
			return InternalShow(message, title, commands).AsAsyncOperation();
		}

		public IMessageDialog MessageDialog(string message, string title)
		{
			return new MessageDialogWrapper(message, title);
		}

		public IAsyncOperation<SystemMessageBoxResult> ShowSystemMessageBox(string message)
		{
			return InternalShowSystemMessageBox(message, null, SystemMessageBoxButton.OK).AsAsyncOperation();
		}

		public IAsyncOperation<SystemMessageBoxResult> ShowSystemMessageBox(string message, string title, SystemMessageBoxButton button)
		{
			return InternalShowSystemMessageBox(message, title, button).AsAsyncOperation();
		}

		private async Task<SystemMessageBoxResult> InternalShowSystemMessageBox(string message, string title, SystemMessageBoxButton button)
		{
			MessageDialog newDialog = null;

			if (!string.IsNullOrEmpty(title))
			{
				newDialog = new MessageDialog(message, title);
			}
			else
			{
				newDialog = new MessageDialog(message);
			}

			ResourceLoader resourceLoader = new ResourceLoader("StyleMVVM/Resources");

			string okString = resourceLoader.GetString("OkString");
			string cancelString = resourceLoader.GetString("CancelString");

			newDialog.Commands.Add(new UICommand(okString));

			if (button == SystemMessageBoxButton.OKCancel)
			{
				newDialog.Commands.Add(new UICommand(cancelString));
			}

			IUICommand command = await newDialog.ShowAsync();

			if (command.Label == okString)
			{
				return SystemMessageBoxResult.OK;
			}

			return SystemMessageBoxResult.Cancel;
		}

		private async Task<string> InternalShow(string message, string title = null, params string[] commands)
		{
			MessageDialog newDialog = null;

			if (!string.IsNullOrEmpty(title))
			{
				newDialog = new MessageDialog(message, title);
			}
			else
			{
				newDialog = new MessageDialog(message);
			}

			if (commands != null)
			{
				foreach (string commandName in commands)
				{
					newDialog.Commands.Add(new UICommand(commandName));
				}
			}
			else
			{
				newDialog.Commands.Add(new UICommand("Ok"));
			}

			IUICommand command = await newDialog.ShowAsync();

			return command.Label;
		}

#elif WINDOWS_PHONE

		public void Notify(string message)
		{
			MessageBox.Show(message);
		}

		public void Notify(string message, string title)
		{
			MessageBox.Show(message, title, MessageBoxButton.OK);
		}

		public async Task<string> Show(string message)
		{
			await ShowSystemMessageBox(message);

			return Resources.OkString;
		}

#elif DOT_NET

		public void Notify(string message)
		{
			Show(message, null);
		}

		public void Notify(string message, string title)
		{
			Show(message, title);
		}

		public Task<string> Show(string message)
		{
			return Show(message, null);
		}

		public void Notify(string message, string title, string buttonText)
		{
			List<MessageBoxCommand> commands = new List<MessageBoxCommand>
				                                   {
					                                   new MessageBoxCommand { DisplayString = buttonText, IsDefault = true }
				                                   };

			Show(message, title, commands);
		}

		public async Task<string> Show(string message, string title, params string[] commands)
		{
			List<MessageBoxCommand> commandsList = new List<MessageBoxCommand>();

			if (commands != null)
			{
				foreach (string commandString in commands)
				{
					commandsList.Add(new MessageBoxCommand { DisplayString = commandString });
				}

				if (commandsList.Count > 0)
				{
					commandsList[0].IsDefault = true;
				}
			}

			MessageBoxCommand selectedCommand = await Show(message, title, commandsList);

			if (selectedCommand != null)
			{
				return selectedCommand.DisplayString;
			}

			return null;
		}

		public Task<MessageBoxCommand> Show(string message,
		                                    string title,
		                                    MessageBoxCommand command,
		                                    params MessageBoxCommand[] commands)
		{
			List<MessageBoxCommand> commandList = new List<MessageBoxCommand>();

			if (command != null)
			{
				commandList.Add(command);
			}

			if (commands != null)
			{
				commandList.AddRange(commands);
			}

			return Show(message, title, commandList);
		}

		public Task<MessageBoxCommand> Show(string message, string title, IEnumerable<MessageBoxCommand> commands)
		{
			MessageBoxWindow window = new MessageBoxWindow { Message = message, Title = title };

			if (commands != null)
			{
				window.Commands = new ObservableCollection<MessageBoxCommand>(commands);
			}

			if (window.Commands == null || window.Commands.Count == 0)
			{
				window.Commands = new ObservableCollection<MessageBoxCommand>
					                  {
						                  new MessageBoxCommand
							                  {
								                  DisplayString = Resources.OkString,
								                  IsDefault = true
							                  }
					                  };
			}

			window.ShowDialog();

			return TaskHelper.ReturnTask(window.SelectedCommand);
		}

#endif

#if !NETFX_CORE

		public async Task<SystemMessageBoxResult> ShowSystemMessageBox(string message)
		{
			return (SystemMessageBoxResult)MessageBox.Show(message);
		}

		public async Task<SystemMessageBoxResult> ShowSystemMessageBox(string message,
		                                                               string title,
		                                                               SystemMessageBoxButton button)
		{
			return (SystemMessageBoxResult)MessageBox.Show(message, title, (MessageBoxButton)button);
		}
#endif
	}
}